#include "uthread.h"
#include <stdlib.h>
#include <unistd.h>

namespace log4x
{
static pthread_key_t  key  = -1;
static pthread_once_t once = PTHREAD_ONCE_INIT;

static void
TLS_free(void* ptr)
{
    free(ptr);
}

static void
TLS_key_create()
{
    pthread_key_create(&key, TLS_free);
}

typedef void* (*THREADENTRY)(void* , int);
typedef struct
{
    THREADENTRY    entry;
    int            id;
    void         * data;
} arg_s;

static void*
address(void* data)
{
    arg_s *arg = (arg_s *)data;

    arg->entry(arg->data, arg->id);
    delete arg;

    return NULL;
}

void
uthread::sleep(long ms)
{
    usleep(ms * 1000);
}

THREAD
uthread::start(void* (* entry)(void* , int), void* data, int id)
{
    THREAD t = 0;

    arg_s *arg = new arg_s();
    arg->entry = entry;
    arg->id    = id;
    arg->data  = data;

    if (0 != pthread_create(&t, NULL, address, arg))
    {
        return 0;
    }

    return t;
}

void
uthread::end(THREAD &t, int timeout)
{
    if (t)
    {
        pthread_join(t, NULL);
        t = 0;
    }
}

void
uthread::detach(THREAD &t)
{
    if (t)
    {
        pthread_detach(t);
    }
}

long
uthread::tid()
{
    return (long)pthread_self();
}

void      *
uthread::get_tls()
{
    pthread_once(&once, TLS_key_create);
    return pthread_getspecific(key);
}

void
uthread::set_tls(void* val)
{
    pthread_once(&once, TLS_key_create);
    pthread_setspecific(key, val);
}

void
uthread::init_mutex(MUTEX &mtx)
{
    pthread_mutex_init(&mtx, NULL);
}

void
uthread::uninit_mutex(MUTEX &mtx)
{
    pthread_mutex_destroy(&mtx);
}

void
uthread::lock(MUTEX &mtx)
{
    pthread_mutex_lock(&mtx);
}

void
uthread::unlock(MUTEX &mtx)
{
    pthread_mutex_unlock(&mtx);
}
}
